﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.IO;
using System.Configuration;
using System.Xml;

namespace Logging
{
    public class Logger
    {
        private Logger()
        {
            m_appenders = new List<ILogAppender>();
        }

        public static Logger Instance
        {
            get
            {
                if (m_instance == null)
                {
                    m_instance = new Logger();
                    string confFile = System.AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
                    XmlDocument xmlDoc = new XmlDocument();
                    xmlDoc.Load(confFile);
                    XmlElement appenderSetting = xmlDoc.SelectSingleNode("configuration/logger/appenders") as XmlElement;
                    foreach (XmlNode node in appenderSetting.ChildNodes)
                    {
                        XmlElement appender = node as XmlElement;
                        string typeName = appender.Attributes["type"].Value;
                        Type t = Type.GetType(typeName);
                        m_instance.RegisterAppender(t);
                    }
                }
                return m_instance;
            }
        }

        public void Error(string format, params object[] args)
        {
            LogLine(LogLevel.ERROR, string.Format(format, args));
        }

        public void Info(string format, params object[] args)
        {
            LogLine(LogLevel.INFO, string.Format(format, args));
        }

        public void Debug(string format, params object[] args)
        {
            LogLine(LogLevel.DEBUG, string.Format(format, args));
        }

        public void Warning(string format, params object[] args)
        {
            LogLine(LogLevel.WARN, string.Format(format, args));
        }

        public void RegisterAppender(Type Appender)
        {
            ILogAppender appender = Activator.CreateInstance(Appender) as ILogAppender;

            try
            {
                m_appenders.Add(appender);
            }
            catch (Exception ex)
            {
                string e = ex.Message;
            }
        }

        private string GetCallerName()
        {
            StackTrace st = new StackTrace();
            StackFrame[] sfs = st.GetFrames();
            foreach (StackFrame sf in sfs)
            {

                if (sf.GetMethod().ReflectedType != this.GetType())
                {
                    return sf.GetMethod().Name;
                }
            }
            return null;
        }

        private string GetDatatime()
        {
            return DateTime.Now.ToString(m_datePattern, System.Globalization.DateTimeFormatInfo.InvariantInfo);
        }

        private void LogLine(LogLevel level, string text)
        {
            string header = string.Format("{0}:{1}:", GetDatatime(), GetCallerName());
            string strLevel = level.ToString();
            text = header + text;
            foreach (ILogAppender appender in m_appenders)
            {
                appender.AppendLine(text);
            }
        }


        List<ILogAppender> m_appenders;
        private static Logger m_instance;
        private string m_datePattern = "yyyy-MM-dd";
        //private LogLevel m_logLeval;

    }

    public enum LogLevel
    {
        DEBUG = 0,
        INFO = 1,
        WARN = 2,
        ERROR = 3
    }
}
